package com.jy.datapipeline.importserver.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.exception.ExcelAnalysisStopException;
import com.jy.datapipeline.common.util.*;
import com.jy.datapipeline.export.entity.DataStoreInfoModel;
import com.jy.datapipeline.common.constants.ExpConstants;
import com.jy.datapipeline.common.constants.FormatConstants;
import com.jy.datapipeline.common.constants.PrefixConstants;
import com.jy.datapipeline.importserver.common.constants.KeyConstant;
import com.jy.datapipeline.importserver.common.constants.TaskConstant;
import com.jy.datapipeline.importserver.common.dto.ImportDataSourceNamesDto;
import com.jy.datapipeline.importserver.common.dto.ImportStoreDto;
import com.jy.datapipeline.importserver.common.dto.TaskTemplateDto;
import com.jy.datapipeline.importserver.common.enums.impl.DataIntervalUnitEnum;
import com.jy.datapipeline.importserver.common.enums.impl.ReturnEnum;
import com.jy.datapipeline.importserver.common.enums.impl.TaskStatusEnum;
import com.jy.datapipeline.importserver.common.enums.impl.TaskTypeEnum;
import com.jy.datapipeline.common.exception.GlobalException;
import com.jy.datapipeline.common.vo.ReturnVo;
import com.jy.datapipeline.importserver.entity.ImportRule;
import com.jy.datapipeline.importserver.entity.ImportRuleTable;
import com.jy.datapipeline.importserver.entity.ImportSubtask;
import com.jy.datapipeline.importserver.entity.ImportTask;
import com.jy.datapipeline.importserver.entity.manager.EntityManager;
import com.jy.datapipeline.importserver.mapper.ImportTaskMapper;
import com.jy.datapipeline.importserver.service.*;
import com.jy.datapipeline.importserver.support.ImportSubtaskSupport;
import com.jy.datapipeline.importserver.support.ImportTaskSupport;
import com.jy.datapipeline.importserver.support.QuartzSupport;
import com.mysql.cj.util.StringUtils;
import lombok.SneakyThrows;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.quartz.CronExpression;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @类名 ImportTaskServiceImpl
 * @描述 TODO
 * @作者 白条君
 * @创建日期 2023/4/18 19:07
 * @版本 1.0
 */
@Service
public class ImportTaskServiceImpl implements ImportTaskService {

    @Resource
    private ImportTaskMapper importTaskMapper;

    private final ImportDataSourceService importDataSourceService;

    private final ImportStoreService importStoreService;

    private final ThreadPoolExecutor executor;

    private final Scheduler scheduler;

    private final ImportRuleService importRuleService;

    private final ImportSubtaskSupport importSubtaskSupport;

    private final ImportSubTaskService importSubTaskService;

    private final ImportRuleTableService importRuleTableService;

    private final QuartzSupport quartzSupport;

    @Lazy
    private final ImportTaskLogService importTaskLogService;

    public ImportTaskServiceImpl(ImportDataSourceService importDataSourceService, ImportStoreService importStoreService,
                                 ThreadPoolExecutor executor, Scheduler scheduler, ImportRuleService importRuleService,
                                 ImportSubtaskSupport importSubtaskSupport, ImportSubTaskService importSubTaskService,
                                 ImportRuleTableService importRuleTableService, QuartzSupport quartzSupport,
                                 ImportTaskLogService importTaskLogService) {
        this.importDataSourceService = importDataSourceService;
        this.importStoreService = importStoreService;
        this.executor = executor;
        this.scheduler = scheduler;
        this.importRuleService = importRuleService;
        this.importSubtaskSupport = importSubtaskSupport;
        this.importSubTaskService = importSubTaskService;
        this.importRuleTableService = importRuleTableService;
        this.quartzSupport = quartzSupport;
        this.importTaskLogService = importTaskLogService;
    }

    @Override
    public ReturnVo queryByPage(Long pageNo, Long pageSize, String taskId, String taskType, String targetDataSourceId, String storeId,
                                String taskStatus, String ruleId, Integer trySubtaskLoadCount, String latestStatus) throws GlobalException, InterruptedException {

        CountDownLatch latch = new CountDownLatch(3);

        /**
         * 分页获取任务信息
         */
        AtomicReference<List<ImportTask>> importTasksReference = new AtomicReference<>();
        executor.execute(() -> {
            Long finalPageNo = (pageNo - 1) * pageSize;
            try {
                importTasksReference.set(importTaskMapper.selectByPage(finalPageNo, pageSize, taskId, taskType, taskStatus, targetDataSourceId, storeId, ruleId, trySubtaskLoadCount));
            } finally {
                latch.countDown();
            }
        });

        /**
         * 获取存储信息到任务中
         */
        AtomicReference<List<ImportStoreDto>> storeNameDtoReference = new AtomicReference<>();
        executor.execute(() -> {
            try {
                storeNameDtoReference.set(importStoreService.queryAllNames());
            } finally {
                latch.countDown();
            }
        });

        /**
         * 获取数据源信息到任务中
         */
        AtomicReference<List<ImportDataSourceNamesDto>> dataSourceNamesDtoReference = new AtomicReference<>();
        executor.execute(() -> {
            try {
                dataSourceNamesDtoReference.set(importDataSourceService.queryDataSourceNames());
            } finally {
                latch.countDown();
            }
        });

        latch.await();

        List<ImportTask> importTasks = importTasksReference.get();
        List<ImportStoreDto> storeNameDtos = storeNameDtoReference.get();
        List<ImportDataSourceNamesDto> dataSourceNamesDtos = dataSourceNamesDtoReference.get();

        List<ImportTask> importTaskList = new ArrayList<>();

        Iterator<ImportTask> iterator = importTasks.iterator();
        while (iterator.hasNext()) {
            ImportTask importTask = iterator.next();
            for (ImportStoreDto storeNameDto : storeNameDtos) {
                if (importTask.getStoreId().equals(storeNameDto.getStore_id())) {
                    importTask.setStoreName(storeNameDto.getStore_name());
                    importTask.setStoreType(storeNameDto.getStore_type());
                }
            }

            for (ImportDataSourceNamesDto dataSourceNameDto : dataSourceNamesDtos) {
                if (dataSourceNameDto.getData_source_id().equals(importTask.getDataSourceId())) {
                    importTask.setDataSourceName(dataSourceNameDto.getData_source_name());
                }
            }

            /**
             * 获取二级任务最近执行状态
             */
            String id = importTask.getTaskId();
            ImportSubtask importSubtask = importSubTaskService.queryLatestStatus(id);
            if (ObjectUtil.isNotNull(importSubtask) && id.equals(importSubtask.getTaskId())) {
                String subtaskStatus = importSubtask.getSubtaskStatus();
                importTask.setLatestStatus(subtaskStatus);
                importTaskMapper.updateLatestStatus(ImportTask.builder().taskId(id).latestStatus(subtaskStatus).build());
            }

            importTask.setDataSourceId(null);
            importTaskList.add(importTask);
            iterator.remove();
        }

        //返回匹配最新执行状态的导入任务
        if (!StringUtils.isNullOrEmpty(latestStatus)) {
            importTaskList = importTaskList.stream()
                    .filter(importTask -> latestStatus.equals(importTask.getLatestStatus()))
                    .collect(Collectors.toList());
        }

        Long totalSize = importTaskMapper.selectTotalSize(taskId, taskType, taskStatus, targetDataSourceId, storeId, ruleId, trySubtaskLoadCount, latestStatus);
        Long totalPage = PageUtil.getTotalPage(totalSize, pageSize);
        return ReturnVo.ok().put(importTaskList).put("totalSize", totalSize).put("totalPage", totalPage);
    }

    @Override
    public void addTask(ImportTask importTask) throws SchedulerException {
        String taskName = importTask.getTaskName();
        String ruleId = importTask.getRuleId();
        String storeId = importTask.getStoreId();
        String taskType = importTask.getTaskType();

        if (StringUtils.isNullOrEmpty(taskName) || StringUtils.isNullOrEmpty(storeId) ||
                StringUtils.isNullOrEmpty(taskType) || StringUtils.isNullOrEmpty(ruleId)) {
            throw new GlobalException(ReturnEnum.PARAM_ERROR.getCode(), ExpConstants.PARAMS_EXP);
        }

        //判断任务名称是否已经存在
        Integer sameName = importTaskMapper.selectSameName(taskName);
        if (sameName != null) {
            throw new GlobalException(ExpConstants.SAME_TASK_NAME_EXP);
        }

        if (String.valueOf(TaskTypeEnum.HAND_EXECUTE.getCode()).equals(importTask.getTaskType())) {
            Date nextStartTime = importTask.getNextStartTime();
            if (nextStartTime != null) {
                throw new GlobalException(ExpConstants.ADD_DATE_PARAM_EXP);
            }
        }

        //配置重试时间间隔和次数
        ImportTaskSupport.configSubtaskRetryPlant(importTask);

        //手动执行状态
        importTask.setTaskStatus(String.valueOf(TaskStatusEnum.NOT_START.getCode()));

        Date nextStartTime = null;
        String cornTab = null;
        if (Integer.valueOf(taskType).equals(TaskTypeEnum.AUTO_EXECUTE.getCode())) {
            Integer value = importTask.getDataIntervalValue();
            String unit = importTask.getDataIntervalUnit();
            nextStartTime = importTask.getNextStartTime();
            cornTab = importTask.getCornTab();
            if (ObjectUtil.isNull(value) || StringUtils.isNullOrEmpty(unit) || ObjectUtil.isNull(nextStartTime) || StringUtils.isNullOrEmpty(cornTab)) {
                throw new GlobalException(ReturnEnum.PARAM_ERROR.getCode(), ExpConstants.PARAMS_EXP);
            }

            //自动执行状态
            importTask.setTaskStatus(String.valueOf(TaskStatusEnum.RUNNING.getCode()));
        }

        String taskId = StringUtil.concat(new StringBuffer(), PrefixConstants.TASK_PREFIX, "_", SnowFlakeUtil.getNextId().toString());
        importTask.setTaskId(taskId);

        //添加sqlldrinfoid
        ImportRule importRule = importRuleService.selectImportRule(ruleId);
        importTask.setSqlldrInfoId(importRule.getSqlldrInfoId());
        importTask.setUpdateTime(DateTimeUtil.getNow());

        int res = importTaskMapper.insertSelective(importTask);
        if (res == 0) {
            throw new GlobalException(ReturnEnum.SERVER_ERROR.getCode(), ExpConstants.ADD_FAIL);
        }

        //如果是自动执行类型的任务就创建新的任务实例和触发器并加入到调度器
        if (Integer.valueOf(taskType).equals(TaskTypeEnum.AUTO_EXECUTE.getCode())) {
            quartzSupport.createScheduledTask(taskId, cornTab, nextStartTime);
        }
    }

    @Override
    public ImportTask queryOneById(Long id) {
        return importTaskMapper.selectDetailsById(id);
    }

    @Override
    public void modifyTask(ImportTask importTask) throws GlobalException, SchedulerException {
        Long id = importTask.getId();
        String taskName = importTask.getTaskName();
        String ruleId = importTask.getRuleId();
        String storeId = importTask.getStoreId();
        String taskType = importTask.getTaskType();
        if (StringUtils.isNullOrEmpty(taskName) || StringUtils.isNullOrEmpty(storeId) ||
                StringUtils.isNullOrEmpty(taskType) || StringUtils.isNullOrEmpty(ruleId) || ObjectUtil.isNull(id)) {
            throw new GlobalException(ReturnEnum.PARAM_ERROR.getCode(), ExpConstants.PARAMS_EXP);
        }

        //配置重试时间间隔和次数
        ImportTaskSupport.configSubtaskRetryPlant(importTask);

        //判断任务名称是否已经存在
        Integer sameName = importTaskMapper.selectSameName(taskName, id);
        if (sameName != null) {
            throw new GlobalException(ExpConstants.SAME_TASK_NAME_EXP);
        }

        Date nextStartTime = null;
        String cornTab = null;
        if (Integer.valueOf(taskType).equals(TaskTypeEnum.AUTO_EXECUTE.getCode())) {
            Integer value = importTask.getDataIntervalValue();
            String unit = importTask.getDataIntervalUnit();
            nextStartTime = importTask.getNextStartTime();
            cornTab = importTask.getCornTab();
            if (ObjectUtil.isNull(value) || StringUtils.isNullOrEmpty(unit) ||
                    ObjectUtil.isNull(nextStartTime) || StringUtils.isNullOrEmpty(cornTab)) {
                throw new GlobalException(ReturnEnum.PARAM_ERROR.getCode(), ExpConstants.PARAMS_EXP);
            }
        }

        String taskId = this.getTaskIds(id).iterator().next();

        //修改任务
        importTask.setUpdateTime(DateTimeUtil.getNow());

        //更新操作
        int res = importTaskMapper.updateByPrimaryKeySelective(importTask);
        AssertUtil.isNull(res, ExpConstants.MODIFY_FAIL);

        if (Integer.valueOf(taskType).equals(TaskTypeEnum.AUTO_EXECUTE.getCode())) {
            quartzSupport.updateScheduledTask(taskId, nextStartTime, cornTab);
        }
    }

    @Override
    public void removeTaskByRuleId(String ruleId) throws SchedulerException {
        Set<Long> ids = importTaskMapper.selectIdsByRuleId(ruleId);
        if (ObjectUtil.isNotNull(ids) && ids.size() > 0) {
            this.deleteTask(ids.toArray(new Long[0]));
        }
    }

    @Transactional
    @Override
    public void deleteTask(Long[] ids) throws GlobalException, SchedulerException {
        //获取taskid
        Set<String> taskIds = importTaskMapper.selectTaskIds(ids);

        //获取subtask的id
        Set<Long> subtaskIds =  importSubTaskService.queryIds(taskIds);

        //删除子任务
        if (ObjectUtil.isNotNull(subtaskIds) && subtaskIds.size() > 0) {
            importSubTaskService.deleteSubTask(subtaskIds.toArray(new Long[0]));
        }

        //查找资源
        Long resource = importTaskMapper.selectResources(ids);
        if (ObjectUtil.isNull(resource) || resource == 0) {
            throw new GlobalException(ReturnEnum.SERVER_ERROR.getCode(), ExpConstants.RESOURCE_EXP);
        }

        //删除任务
        Long res = importTaskMapper.deleteByIds(ids);
        if (ObjectUtil.isNull(res) || res == 0) {
            throw new GlobalException(ReturnEnum.SERVER_ERROR.getCode(), ExpConstants.DELETE_FAIL);
        }

        //删除定时任务
        for (String taskId : taskIds) {
            quartzSupport.delete(taskId, "import_task");
        }
    }

    @Override
    public void pauseTask(Long id) throws GlobalException, SchedulerException {
        //更改状态
        ImportTask task = ImportTask.builder()
                .taskStatus(String.valueOf(TaskStatusEnum.NOT_START.getCode()))
                .nextStartTime(null)
                .updateTime(new Date())
                .id(id).build();
        int res = importTaskMapper.updateByPrimaryKeySelective(task);
        if (ObjectUtil.isNull(res) || res == 0) {
            throw new GlobalException(ReturnEnum.SERVER_ERROR.getCode(), ExpConstants.MODIFY_FAIL);
        }

        Set<String> taskIds = this.getTaskIds(id);
        quartzSupport.pause(taskIds.iterator().next());
    }

    @Override
    public void resumeTask(Long[] ids) throws GlobalException, SchedulerException {
        List<ImportTask> importTasks = importTaskMapper.selectImportTasks(ids);

        //检查是否是自动任务类型
        List<String> taskTypes = importTasks.stream().map(ImportTask::getTaskType).collect(Collectors.toList());
        for (String taskType : taskTypes) {
            if (String.valueOf(TaskTypeEnum.HAND_EXECUTE.getCode()).equals(taskType)) {
                throw new GlobalException(ExpConstants.NOT_SUPPORTED_HAND_TYPE);
            }
        }

        Set<String> taskIds = importTasks.stream().map(ImportTask::getTaskId).collect(Collectors.toSet());
        Iterator<String> iterator = taskIds.iterator();

        ImportTask importTask;
        while (iterator.hasNext()) {
            String taskId = iterator.next();
            scheduler.resumeTrigger(TriggerKey.triggerKey(taskId));

            importTask = (ImportTask) EntityManager.create(KeyConstant.IMPORT_TASK_KEY);
            importTask.setTaskId(taskId);
            importTask.setTaskStatus(String.valueOf(TaskStatusEnum.RUNNING.getCode()));
            importTask.setUpdateTime(new Date());
            int res = importTaskMapper.updateTaskByTaskId(importTask);
            if (ObjectUtil.isNull(res) || res == 0) {
                throw new GlobalException(ReturnEnum.SERVER_ERROR.getCode(), ExpConstants.MODIFY_FAIL);
            }
        }
    }

    @Override
    public void modifyTask(ImportTask importTask, Object... ignore) throws GlobalException {
        int res = importTaskMapper.updateByPrimaryKeySelective(importTask);
        if (res == 0) {
            throw new GlobalException(ReturnEnum.SERVER_ERROR.getCode(), ExpConstants.MODIFY_FAIL);
        }
    }

    private Set<String> getTaskIds(Long... ids) throws GlobalException {
        Set<String> idList = importTaskMapper.selectTaskIds(ids);
        if (ObjectUtil.isNull(idList) || idList.isEmpty()) {
            throw new GlobalException(ReturnEnum.SERVER_ERROR.getCode(), ExpConstants.NULL_OBJECT);
        }
        return idList;
    }

    public void modifyTaskByTaskId(ImportTask importTask) {
        importTaskMapper.updateTaskByTaskId(importTask);
    }

    @Override
    public void startTask(String taskId, Date... nextStartTime) throws GlobalException, ParseException {
        // 根据id获取相关的任务信息
        ImportTask importTask = importTaskMapper.selectByTaskId(taskId);

        if (ObjectUtil.isNull(importTask)) {
            return;
        }

        //获取业务标签
        String businessName = importTask.getBusinessName();

        //获取当前启动时间
        Date startTime = importTask.getNextStartTime();
        if (ObjectUtil.isNull(startTime)) {
            //生成当前启动时间
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            startTime = simpleDateFormat.parse(simpleDateFormat.format(new Date()));
        }
        //启动时间到数据周期的间隔值
        Integer dataIntervalValue = importTask.getDataIntervalValue();
        //数据周期单位
        String dataIntervalUnit = importTask.getDataIntervalUnit();

        //计算数据周期，数据周期=启动时间-数据周期间隔
        Date dataCircleTime = DateTimeUtil.updateDataCircleTime(dataIntervalUnit, -dataIntervalValue, startTime);
        //格式化数据周期
        String dataCircle = DateTimeUtil.formatDataCircle(dataCircleTime, dataIntervalUnit);

        String ruleId = importTask.getRuleId();

        String storeLocation = null;
        List<ImportRuleTable> importRuleTables = importRuleTableService.queryByRuleId(ruleId);
        if (ObjectUtil.isNotNull(importRuleTables) && importRuleTables.size() > 0) {
            //获取文件存储路径
            String storeId = importTask.getStoreId();
            List<ImportStoreDto> importStoreDtos = importStoreService.queryAllNames();
            for (ImportStoreDto importStoreDto : importStoreDtos) {
                if (importStoreDto.getStore_id().equals(storeId)) {
                    String store_name = importStoreDto.getStore_name();
                    storeLocation = importStoreService.queryStoreLocation(store_name);
                    break;
                }
            }
        }

        for (ImportRuleTable importRuleTable : importRuleTables) {
            String sourceTableName = importRuleTable.getSourceTableName();

            //获取sqlldrInfoId和分隔符
            ImportRule importRule = importRuleService.selectImportRule(ruleId);

            //获取目标字段列表
            String targetColumnList = importRuleTableService.queryTargetColumnListByRuleTableId(importRuleTable.getRuleTableId());

            //创建子任务
            ImportSubtask importSubTask
                    = importSubtaskSupport.createSubTask(startTime, taskId, importRuleTable, sourceTableName,
                    businessName, dataCircle, dataCircleTime, importRule, targetColumnList, storeLocation);

            //添加子任务
            importSubTask.setTrySubtaskLoadCount(importTask.getTrySubtaskLoadCount());
            importSubTask.setTrySubtaskLoadInterval(importTask.getTrySubtaskLoadInterval());
            importSubTask.setTrySubtaskLoadCurrentCount(0);
            importSubTaskService.addImportSubTask(importSubTask);

            //更新任务最新执行时间和下一次的执行时间
            ImportTask task = (ImportTask) EntityManager.create(KeyConstant.IMPORT_TASK_KEY);
            task.setId(importTask.getId());
            task.setUpdateTime(new Date());
            task.setLatestStartTime(startTime);
            if (ObjectUtil.isNotNull(nextStartTime) && nextStartTime.length > 0) {
                task.setNextStartTime(nextStartTime[0]);
            }
            try {
                this.modifyTask(task, 0);
            } catch (Exception ignore) {}
        }
    }

    @Override
    public List<ImportTask> queryNames(String taskName) {
        return importTaskMapper.selectNames(taskName);
    }

    private void checkIsNull(TaskTemplateDto taskTemplateDto) {
        AssertUtil.isNull(taskTemplateDto.getTaskName(), ExpConstants.TASK_NAME_NOT_NULL);
        AssertUtil.isNull(taskTemplateDto.getRuleName(), ExpConstants.TASK_RULE_NOT_NULL);
        AssertUtil.isNull(taskTemplateDto.getStoreName(), ExpConstants.TASK_STORE_NOT_NULL);
        AssertUtil.isNull(taskTemplateDto.getTaskType(), ExpConstants.TASK_TYPE_NOT_NULL);
        AssertUtil.isNull(taskTemplateDto.getDataIntervalValue(), ExpConstants.TASK_INTERVAL_VALUE_NOT_NULL);
        AssertUtil.isNull(taskTemplateDto.getDataIntervalUnit(), ExpConstants.TASK_INTERVAL_UNIT_NOT_NULL);
    }

    @Override
    public <T> T analysisExcelRows(T data) {
        TaskTemplateDto taskTemplateDto = ConvertUtil.convertObject(data, TaskTemplateDto.class);
        AssertUtil.isNull(taskTemplateDto, ExpConstants.TYPE_CONVERT_EXP);

        this.checkIsNull(taskTemplateDto);

        //同名校验
        Integer isExists = importTaskMapper.selectSameName(taskTemplateDto.getTaskName());
        AssertUtil.isNotNUll(isExists, ExpConstants.SAME_TASK_NAME_EXP);

        //导入规则校验
        ImportRule importRule = importRuleService.queryOneByRuleName(taskTemplateDto.getRuleName());
        AssertUtil.isNull(importRule, ExpConstants.TASK_RULE_NOT_EXISTS);

        //添加相关id
        taskTemplateDto.setRuleId(importRule.getRuleId());
        taskTemplateDto.setSqlldrInfoId(importRule.getSqlldrInfoId());
        taskTemplateDto.setDataSourceId(importRule.getDataSourceId());

        //存储名称校验
        DataStoreInfoModel dataStoreInfoModel = importStoreService.queryStoreIdByStoreName(taskTemplateDto.getStoreName());
        AssertUtil.isNull(dataStoreInfoModel, ExpConstants.TASK_STORE_NOT_EXISTS);
        taskTemplateDto.setStoreId(dataStoreInfoModel.getStoreId());

        //任务类型校验
        String taskType = taskTemplateDto.getTaskType();
        if (StringUtil.isNumber(taskType)) {
            Integer type = Integer.valueOf(taskType);
            if (!type.equals(TaskTypeEnum.AUTO_EXECUTE.getCode()) && !type.equals(TaskTypeEnum.HAND_EXECUTE.getCode())) {
                throw new ExcelAnalysisStopException(ExpConstants.TASK_TYPE_CONSTRAINT_EXP);
            }
            //定时任务校验
            if (type.equals(TaskTypeEnum.AUTO_EXECUTE.getCode())) {
                String nextStartTime = taskTemplateDto.getNextStartTime();
                if (!DateTimeUtil.isValidDatetimeFormat(nextStartTime, FormatConstants.DATETIME_FORMAT)) {
                    throw new ExcelAnalysisStopException(ExpConstants.INVALID_DATETIME_FORMAT);
                }

                String cornTab = taskTemplateDto.getCornTab();
                AssertUtil.isNull(cornTab, ExpConstants.CORNTAB_NOT_NULL);
                if (!CronExpression.isValidExpression(cornTab.trim())) {
                    throw new ExcelAnalysisStopException(ExpConstants.INVALID_CRONTAB_EXPRESSION);
                }
            }
        } else {
            throw new ExcelAnalysisStopException(ExpConstants.TASK_TYPE_MUST_DIGIT);
        }

        //数据周期单位校验
        String dataIntervalUnit = taskTemplateDto.getDataIntervalUnit();
        if (!StringUtil.isNumber(dataIntervalUnit)) {
            throw new ExcelAnalysisStopException(ExpConstants.TASK_INTERVAL_UNIT_MUST_DIGIT);
        }
        Integer unit = Integer.valueOf(dataIntervalUnit);
        if (!unit.equals(DataIntervalUnitEnum.MONTH.getCode()) && !unit.equals(DataIntervalUnitEnum.DAY.getCode()) &&
        !unit.equals(DataIntervalUnitEnum.HOUR.getCode()) && !unit.equals(DataIntervalUnitEnum.MINUTES.getCode())) {
            throw new ExcelAnalysisStopException(ExpConstants.TASK_INTERVAL_UNIT_CONSTRAINT_EXP);
        }

        return (T) taskTemplateDto;
    }

    @SneakyThrows
    @Override
    public <T> Set<Long> batchSave(List<T> t) {
        List<TaskTemplateDto> taskTemplateDtoList = ConvertUtil.convertArray(t, TaskTemplateDto.class);
        AssertUtil.isNull(taskTemplateDtoList, ExpConstants.TYPE_CONVERT_EXP);

        List<ImportTask> importTasks = new ArrayList<>();
        ImportTask importTask;
        for (TaskTemplateDto taskTemplateDto : taskTemplateDtoList) {
            importTask = (ImportTask) EntityManager.create(KeyConstant.IMPORT_TASK_KEY);
            BeanUtil.copyProperties(taskTemplateDto, importTask);
            ImportTaskSupport.configImportTask(importTask, taskTemplateDto);
            importTasks.add(importTask);
        }

        int size = importTaskMapper.batchInsert(importTasks);
        AssertUtil.totalAffectedRows(size, importTasks, ExpConstants.BATCH_ADD_FAIL);

        //如果是自动执行类型的任务就创建新的任务实例和触发器并加入到调度器
        for (ImportTask task : importTasks) {
            if (Integer.valueOf(task.getTaskType()).equals(TaskTypeEnum.AUTO_EXECUTE.getCode())) {
                quartzSupport.createScheduledTask(task.getTaskId(), task.getCornTab(), task.getNextStartTime());
            }
        }
        return importTasks.stream().map(ImportTask::getId).collect(Collectors.toSet());
    }

    @SneakyThrows
    @Override
    public <T> Long save(T t) {
        TaskTemplateDto taskTemplateDto = ConvertUtil.convertObject(t, TaskTemplateDto.class);
        AssertUtil.isNull(taskTemplateDto, ExpConstants.TYPE_CONVERT_EXP);

        ImportTask importTask = (ImportTask) EntityManager.create(KeyConstant.IMPORT_TASK_KEY);
        BeanUtil.copyProperties(taskTemplateDto, importTask);

        ImportTaskSupport.configImportTask(importTask, taskTemplateDto);

        int res = importTaskMapper.insertSelective(importTask);
        AssertUtil.isNull(res, ExpConstants.ADD_FAIL);

        //如果是自动执行类型的任务就创建新的任务实例和触发器并加入到调度器
        if (Integer.valueOf(importTask.getTaskType()).equals(TaskTypeEnum.AUTO_EXECUTE.getCode())) {
            quartzSupport.createScheduledTask(importTask.getTaskId(), importTask.getCornTab(), importTask.getNextStartTime());
        }

        return importTask.getId();
    }

    @Transactional
    @SneakyThrows
    @Override
    public void batchDelete(Set<Long> ids) {
        List<ImportTask> importTasks = importTaskMapper.selectImportTasks(ids.toArray(new Long[0]));
        Set<String> taskIds = importTasks.stream().map(ImportTask::getTaskId).collect(Collectors.toSet());

        //暂停所有定时任务
        for (String taskId : taskIds) {
            quartzSupport.pause(taskId);
        }

        //获取所有任务下子任务的subtaskid
        List<ImportSubtask> importSubtasks = importSubTaskService.querySubtaskIds(taskIds);

        //批量删除子任务日志、子任务定时记录、子任务
        if (importSubtasks != null && importSubtasks.size() > 0) {

            Set<String> subtaskIds = importSubtasks.stream().map(ImportSubtask::getSubtaskId).collect(Collectors.toSet());

            //批量删除子任务日志
            importTaskLogService.batchRemove(subtaskIds);

            Map<String, String> importTaskMap = importTasks.stream().collect(Collectors.toMap(ImportTask::getTaskId, ImportTask::getTaskType));

            //删除子任务定时记录
            for (ImportTask importTask : importTasks) {
                String taskType = importTaskMap.get(importTask.getTaskId());
                if (String.valueOf(TaskTypeEnum.AUTO_EXECUTE.getCode()).equals(taskType)) {
                    quartzSupport.delete(importTask.getTaskId(), "import_task");
                }
            }

            //删除子任务重试定时记录
            for (ImportSubtask importSubtask : importSubtasks) {
                quartzSupport.delete(PrefixConstants.SUBTASK_PREFIX + "_" + importSubtask.getId(), "import_subtask");
            }

            //删除子任务
            importSubTaskService.batchRemove(subtaskIds);
        }

        //删除任务
        Long size = importTaskMapper.deleteByIds(ids.toArray(new Long[0]));
        AssertUtil.totalAffectedRows(size.intValue(), ids, ExpConstants.BATCH_DELETE_FAIL);
    }
}
